package com.oauth.security.config.shiro;

import com.oauth.security.config.jwt.JwtFilter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Filter;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

/**
 * @author likai
 * @Date 2018/10/18
 */
@Configuration
public class ShiroConfig {

  private static final String JWT_FILTER_NAME = "jwt";

  /**
   * 自定义realm，实现登录授权流程
   */
  @Bean
  public Realm authRealm() {
    return new AuthRealm();
  }

  /**
   * 配置securityManager 管理subject（默认）,并把自定义realm交由manager
   */
  @Bean
  public DefaultSecurityManager securityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(authRealm());
    //非web关闭sessionManager(官网有介绍)
    DefaultSubjectDAO defaultSubjectDAO = new DefaultSubjectDAO();
    DefaultSessionStorageEvaluator storageEvaluator = new DefaultSessionStorageEvaluator();
    storageEvaluator.setSessionStorageEnabled(false);
    defaultSubjectDAO.setSessionStorageEvaluator(storageEvaluator);
    securityManager.setSubjectDAO(defaultSubjectDAO);

    return securityManager;
  }

  /**
   * 拦截链
   */
  @Bean
  public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    shiroFilterFactoryBean.setFilters(filterMap());
    shiroFilterFactoryBean.setFilterChainDefinitionMap(definitionMap());

    return shiroFilterFactoryBean;
  }

  /**
   * 自定义拦截器，处理所有请求
   */
  private Map<String, Filter> filterMap() {
    Map<String, Filter> filterMap = new HashMap<>();
    filterMap.put(JWT_FILTER_NAME, new JwtFilter());
    return filterMap;
  }

  /**
   * url拦截规则
   */
  private Map<String, String> definitionMap() {
    Map<String, String> definitionMap = new HashMap<>();
    definitionMap.put("/login", "anon");
    definitionMap.put("/**", JWT_FILTER_NAME);
    return definitionMap;
  }

  /**
   * 开启注解
   */
  @Bean
  @DependsOn("lifecycleBeanPostProcessor")
  public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    // 强制使用cglib代理，防止和aop冲突
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    return defaultAdvisorAutoProxyCreator;
  }

  @Bean
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }

  @Bean("authorizationAttributeSourceAdvisor")
  public AuthorizationAttributeSourceAdvisor advisor(DefaultSecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
    advisor.setSecurityManager(securityManager);
    return advisor;
  }
}
